package com.ycg.vue.modules.user.service.impl;

import com.ycg.vue.Exception.CustomException;
import com.ycg.vue.constant.Constant;
import com.ycg.vue.context.ThreadLocalContext;
import com.ycg.vue.modules.system.Entity.BillEntity;
import com.ycg.vue.modules.system.VO.BillVO;
import com.ycg.vue.modules.system.mapper.BillMapper;
import com.ycg.vue.modules.user.VO.UserBillVO;
import com.ycg.vue.modules.user.mapper.UserBillMapper;
import com.ycg.vue.modules.user.mapper.UserMapper;
import com.ycg.vue.modules.user.service.UserBillService;
import com.ycg.vue.result.Result;
import com.ycg.vue.utils.UUIDUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author jink
 * @Date 2024/8/14
 */
@Service
public class UserBillServiceImpl implements UserBillService {

    @Resource
    private UserBillMapper userBillMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserServiceImpl userServiceImpl;

    @Resource
    private BillMapper billMapper;

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public Result add(BillEntity bill) {
        try {
            String userId = ThreadLocalContext.getUserId();
            if (userId == null) return Result.error(Constant.USER_STATUS_ERROR);
            bill.setId(UUIDUtils.getUUID());
            bill.setUserId(userId);
            bill.setCreateTime(new Date());
            bill.setUpdateTime(new Date());
            userBillMapper.insert(bill);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException(500, e.getMessage());
        }
    }

    @Override
    public Result select() {
        String userId = ThreadLocalContext.getUserId();
        Set<Integer> result = new HashSet<>();
        List<BillVO> billVO = new ArrayList<>();
        List<Map<String, Object>> billList = billMapper.getBillList(userId, null, null);
        for (Map<String, Object> map : billList) {
            LocalDateTime time = (LocalDateTime) map.get("time");
            result.add(time.getYear());
        }
        result.forEach(y -> {
            List<Map<Object, Object>> dataList = new ArrayList<>();
            Set<Integer> mouthList = new TreeSet<>();
            BillVO vo = new BillVO();
            vo.setYear(y);
            billList.stream().filter(m -> {
                        LocalDateTime time = (LocalDateTime) m.get("time");
                        return y == time.getYear();
                    })
                    .forEach(m -> {
                        LocalDateTime time = (LocalDateTime) m.get("time");
                        mouthList.add(time.getMonthValue());
                    });
            mouthList.forEach(m -> {
                String begin = y + "-" + m + "-01 00:00:00";
                String end = y + "-" + m + "-31 23:59:59";
                List<Map<String, Object>> data = billMapper.getBillList(userId, begin, end);
                Map<Object, Object> dataMap = new HashMap<>();
                dataMap.put(m, data);
                dataList.add(dataMap);
            });
            vo.setMonth(dataList);
            billVO.add(vo);
        });
        return Result.success(billVO);
    }

    @Override
    public Result changeMonth(String month) {
        String userId = ThreadLocalContext.getUserId(), begin = month + "-01 00:00:00", end = month + "-31 23:59:59";
        return Result.success(billMapper.getBillList(userId, begin, end));
    }

    @Override
    public Result selectDaysForMonth(String month) {
        UserBillVO userBillVo = new UserBillVO();
        String userId = ThreadLocalContext.getUserId();
        String begin = month + "-01 00:00:00";
        String end = month + "-31 23:59:59";

        // 一次性获取整个月份的账单列表（包括收入和支出）
        List<Map<String, Object>> billList = billMapper.getBillList(userId, begin, end);
        if (billList.isEmpty()) return Result.success();

        // 使用 Set 存储有账单的日期，并初始化收入和支出 Map
        Set<Integer> result = new TreeSet<>();
        Map<String, Double> incomeData = new HashMap<>();
        Map<String, Double> expenseData = new HashMap<>();

        billList.forEach(bill -> {
            LocalDateTime dateTime = (LocalDateTime) bill.get("time");
            int day = dateTime.getDayOfMonth();
            String dayKey = month + "-" + (day < 10 ? "0" + day : day);

            result.add(day);
            Double amount = Double.parseDouble(bill.get("price").toString());
            int type = Integer.parseInt(bill.get("type").toString());
            DecimalFormat df = new DecimalFormat("0.00");
            if (type == 1) {
                amount = incomeData.getOrDefault(dayKey, 0.0) + amount;
                incomeData.put(dayKey, Double.valueOf(df.format(amount)));
            } else {
                amount = expenseData.getOrDefault(dayKey, 0.0) + amount;
                expenseData.put(dayKey, Double.valueOf(df.format(amount)));
            }
        });

        // 设置 UserBillVO 数据
        userBillVo.setDays(new ArrayList<>(result));
        userBillVo.setIncomeData(incomeData);
        userBillVo.setExpenseData(expenseData);

        return Result.success(userBillVo);
    }

    @Override
    public Result situation(String day, Integer type) {
        String userId = ThreadLocalContext.getUserId();
        String begin = day + " 00:00:00";
        String end = day + " 23:59:59";
        return Result.success(billMapper.situation(userId,begin,end,type));
    }
}
